
#include <stdlib.h>
#include "memory.h"
#include "vector.h"



eruta_struct(Vector) {
    size_t _elsize;
    size_t _size;
    eruta_pointer_pointer _data; 
};

Vector vector_make(size_t elsize, size_t initsize) {
    Vector self     = eruta_make(Vector);
    self->_size     = initsize;
    self->_elsize   = elsize;
    self->_data     = eruta_allocate(initsize * elsize);
    return self;
}

Vector vector_free(Vector self) {
    eruta_free(self->_data);
    eruta_free(self);            
    return NULL;
}

size_t vector_size(Vector self) {
    return self->_size;
}

size_t vector_element_size(Vector self) {
    return self->_elsize;
}

eruta_pointer vector_get(Vector self, size_t index) {
    if( self->_size <= index ) return NULL;
    if( ((signed int)index) < 0 ) return NULL;
    return self->_data[index];
}

Vector vector_set(Vector self, size_t index, eruta_pointer value) {
    if( self->_size <= index) return NULL;
    if( ((signed int)index) < 0 ) return NULL;
    self->_data[index] = value;
    return self;
}

Vector vector_copy(Vector self, Vector target) {
    size_t stop = vector_size(self);
	size_t index =0;
    if (stop > vector_size(target)) { 
        stop = vector_size(target);
    }
    for(index = 0; index < stop; index++ ) {
        vector_set(target, index, vector_get(self, index));
    }
    return self;
}

Vector vector_grow(Vector self, size_t newsize) {
    Vector newvector = vector_make(self->_elsize, newsize);
    vector_copy(self, newvector);
    return newvector;
}

Vector vector_grow_kill(Vector self, size_t newsize) {
    Vector newvector = vector_make(self->_elsize, newsize);
    vector_copy(self, newvector);
    vector_free(self);
    return newvector;
}

Vector vector_set_grow(Vector self, size_t index, eruta_pointer value) {
    size_t newsize;
	Vector result;
	if( ((signed int)index) < 0 ) return NULL;
    newsize   = index > vector_size(self) ? index :  vector_size(self);
    result = vector_grow(self, newsize); 
    return vector_set(result, index, value);
}

Vector vector_each(Vector self , vector_each_callback callback) {
    size_t index = 0;
	size_t stop = vector_size(self);
    for(index = 0; index < stop; index ++ ) {
        eruta_pointer value         = vector_get(self, index);
        eruta_pointer newvalue      = callback(value);
        if(value != newvalue) {      
            vector_set(self, index, newvalue);            
        }
    }
    return self;
}
